home *** CD-ROM | disk | FTP | other *** search
- /*
- * gencif.c
- * Gianni Mariani 3-Dec-1993
- *
- * Generalized call interface
- */
-
- #include <alloca.h>
- #include "gencall.h"
-
- /* ======== gcif_Prefunc ============================================== */
- /* PURPOSE:
- * To be used with CallFromGeneralArgs as the prep func. It takes
- * the description of the arguments in GCIF_CALLDESC and generates
- * a call frame for the function call described therin.
- *
- * RETURNS:
- * Nothing
- */
-
- void gcif_Prefunc(
- char * call_args, /* Address of first arg to func */
- GCIF_CALLDESC * args, /* As passed in CallFromGeneralArgs */
- int bytes, /* As passed in CallFromGeneralArgs */
- unsigned * p_flags /* Pointer to the value "flags" */
- ) {
-
- register GCIF_ARG * p_arg; /* Pointer to arg descriptor */
- register void ** p_argv; /* Pointer to argvalue */
- register int i;
- register char * argp; /* Pointer to actual arg */
- register int avn;
- register int tmp;
-
- tmp = 0;
- argp = call_args;
- /* If the return type is a struct then */
- if ( args->gcif_rettype == gcif_struct ) {
-
- /* If the return type is a struct then the pointer to the */
- /* struct is the first arg */
-
- * ( void ** ) argp = args->gcif_retv;
- argp += 4;
- }
-
- /* go through all the args and insert them */
- avn = args->gcif_nargv;
- p_argv = args->gcif_argv;
-
- for (
- i = args->gcif_nargs, p_arg = args->gcif_args;
- i && avn;
- i --, p_arg ++
- ) {
- int z;
-
- /* Do we need aligning */
- if ( ( p_arg->gcif_align - 1 ) & ( unsigned ) argp ) {
- argp = ( char * ) GCIF_ALIGN( argp, p_arg->gcif_align );
- }
-
- if ( avn ) {
- avn --;
- if ( p_arg->gcif_type <= gcif_float ) {
- * ( int * ) argp = * ( int * )( * p_argv );
- z = 4;
- } else if ( p_arg->gcif_type == gcif_double ) {
- * ( double * ) argp = * ( double * )( * p_argv );
- z = 8;
- } else {
- z = p_arg->gcif_size;
- if ( z < 4 ) {
- switch( p_arg->gcif_type ) {
- case gcif_char :
- if ( 0 > ( char ) 0xff ) {
- * ( unsigned * ) argp = * ( char * ) ( * p_argv );
- } else {
- * ( signed * ) argp = * ( char * ) ( * p_argv );
- }
- break;
- case gcif_uchar :
- * ( unsigned * ) argp = * ( gcif_uchar_t * ) ( * p_argv );
- break;
- case gcif_schar :
- * ( signed * ) argp = * ( gcif_schar_t * ) ( * p_argv );
- break;
- case gcif_ushort :
- * ( unsigned * ) argp = * ( gcif_ushort_t * ) ( * p_argv );
- break;
- case gcif_sshort :
- * ( signed * ) argp = * ( gcif_sshort_t * ) ( * p_argv );
- break;
- default:
- memcpy( argp, * p_argv, z );
- break;
- }
- z = 4;
- } else {
- memcpy( argp, * p_argv, z );
- }
- }
- p_argv ++;
- argp += z;
- }
- }
-
- return;
-
- } /* end gcif_Prefunc */
-
-
- /* ======== gcif_call ================================================= */
- /* PURPOSE:
- * Call a function with arguments described in the call description
- * structure GCIF_CALLDESC. It also takes care of making a return
- * address for functions returning structures.
- *
- * RETURNS:
- * Whatever func returns if it is not returning a struct.
- */
-
- int gcif_call(
- GCIF_FUNC_T func,
- GCIF_CALLDESC * args
- ) {
-
- void * retaddr;
-
- /* If the return value is a struct and we don't have a return */
- /* value address then we need to make one */
- if (
- ( ! ( retaddr = args->gcif_retv ) )
- && ( args->gcif_rettype == gcif_struct )
- ) {
- retaddr = alloca( args->gcif_retsize );
- }
-
- return CallFromGeneralArgs(
- gcif_Prefunc,
- args,
- args->gcif_bytes,
- args->gcif_flags,
- args->gcif_retv,
- func
- );
-
- } /* end gcif_call */
-
-
- /* ======== gcif_filldesc ============================================= */
- /* PURPOSE:
- * Fill the call descriptor fields gcif_bytes and gcif_flags.
- *
- * RETURNS:
- *
- */
-
- void gcif_filldesc(
- GCIF_CALLDESC * args
- ) {
-
- register unsigned bytes = 0;
- register int i;
- register GCIF_ARG * p_arg; /* Pointer to arg descriptor */
-
- i = args->gcif_nargs;
- p_arg = args->gcif_args;
- if ( args->gcif_rettype == gcif_struct ) {
- bytes = 4;
- args->gcif_flags = GCIF_MKFLAGS(
- args->gcif_rettype & ( RET_FP_MASK | RETINT ),
- FP_PASS( gcif_void, gcif_void )
- );
- } else {
- bytes = 0;
- args->gcif_flags = GCIF_MKFLAGS(
- args->gcif_rettype & ( RET_FP_MASK | RETINT ),
- FP_PASS(
- i>0 ? p_arg[ 0 ].gcif_type & RET_FP_MASK : gcif_void,
- i>1 ? p_arg[ 1 ].gcif_type & RET_FP_MASK : gcif_void
- )
- );
-
- }
-
- /* Find the size required */
- for ( ; i; i --, p_arg++) {
-
- if ( ( p_arg->gcif_align - 1 ) & bytes ) {
- bytes = GCIF_ALIGN( bytes, p_arg->gcif_align );
- }
-
- bytes += p_arg->gcif_size;
- }
-
- args->gcif_bytes = bytes;
-
- return;
-
- } /* end gcif_filldesc */
-
-
-